<!DOCTYPE html>
<html lang="zh">

	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>室内定位</title>
		<link rel="stylesheet" href="lib/bootstrap.min.css">
		<link rel="stylesheet" href="css/style.css?aa=22">
	</head>

	<body>
		<div id="fengMap"></div>
		<!--距离时间显示-->
		<div id="description"></div>
		<!--去这里按钮-->
		<div id="navigation" class="genre-list-single-gohere genre-list-gohere">
			<img src="image/go-here.png">
			<div>去这里</div>
		</div>
		<script src="util/math.js" type="text/javascript" charset="utf-8"></script>
		<script src="lib/fengmap.min.js"></script>
		<script src="util/km.js" type="text/javascript" charset="utf-8"></script>
		<script src="util/data.js" type="text/javascript" charset="utf-8"></script>
		<script src="lib/jquery-2.1.4.min.js"></script>
		<script src="util/jibu.js" type="text/javascript" charset="utf-8"></script>
		<script src="util/websocket.js" type="text/javascript" charset="utf-8"></script>

		<script type="text/javascript">
			var _qValue = 0.001;
			var _rValue = 0.01;
			//坐标点下标
			var coordIndex = 0;
			//起点终点坐标
			var points = [{
					x: 13028218.4785,
					y: 4737039.7298,
					groupID: 1
				},
				{
					x: 13028218.4785,
					y: 4737009.7298,
					groupID: 1
				}
			];
			var naviState = false; //导航状态，是否导航中
			// 导航对象
			var navi = null;
			var XYobj = {};

			var resultX = 31;
			var resultY = 12;

			var zhuanhuanXY; //地图坐标

			var Ldirection = 180; //浏览器方向

			var newCoord = {
				x: 0,
				y: 0
			}
			var locationCount = 0;

			//获取版本号,设置title
			document.title = '室内定位' + fengmap.VERSION;

			//定义全局map变量
			var map;
			var fmapID = 'location-test';
			var locationMarker;
			//楼层ID
			var lastGid = null;
			//第一人称、第三人称控制开关；定位跟随开关
			var others = true;
			var layer = null

			window.onload = function() {
				var mapCoord = {
					x: 13028218.4785,
					y: 4737030.7298,
					groupID: 1
				}; // websocket传过来的坐标信息，经过转换的可直接在地图上显示。
				map = new fengmap.FMMap({
					//渲染dom
					container: document.getElementById('fengMap'),
					//地图数据位置
					mapServerURL: './data/' + fmapID,
					//主题数据位置
					mapThemeURL: 'data/theme/',
					//设置主题
					defaultThemeName: '2001',
					// 默认比例尺级别设置为20级
					defaultMapScaleLevel: 22,
					//开启2维，3维切换的动画显示
					viewModeAnimateMode: true,
					//方向枚举型。可设置正南、正北、正东、正西、东南、西南等方向值。具体可参考fengmap.ControlsPoseEnum类。NORTH WEST SOUTH
					defaultControlsPose: fengmap.FMDirection.NORTH,
					defaultViewMode: fengmap.FMViewMode.MODE_2D, //初始二维还是三维状态，三维状态为MODE_3D,

					//开发者申请应用下web服务的key
					key: '670072019dff394f3f991e88e98024d5',
					//开发者申请应用名称
					appName: 'innerMap',
				});

				//打开Fengmap服务器的地图数据和主题
				map.openMapById(fmapID);

				//显示指北针
				map.showCompass = true;
				//地图加载完成回调
				map.on('loadComplete', function() {
					FengZhuangXY();
					//					WebSocketTest();
					//初始化导航对象
					navi = new fengmap.FMNavigation({
						map: map,
						// 设置导航线的样式
						lineStyle: {
							//设置线为导航线样式
							lineType: fengmap.FMLineType.FMARROW,
							lineWidth: 6,
						}
					});
					var zhuanXY = {
						x: resultX,
						y: resultY,
					}
					var coord = CoordTransform(zhuanXY);
					coord.groupID = 1;
					addlocationMarker(coord);
					// 设置导航事件
					navi.on('walking', function(data) {
						console.log('data', data)
						setLocationMakerPosition(data.point, data.angle);
						
						//显示导航展示信息
						cardInfo(data);
					});
				});

				//设置图片标注点位置信息
				function setLocationMakerPosition(coord, angle) {
					var data = {
						//设置定位点的x坐标
						x: coord.x,
						//设置定位点的y坐标
						y: coord.y,
						//设置定位点所在楼层
						groupID: coord.groupID,
						time: .50,
						callback: function() {
							//回调函数
						},
						zOffset: 1
					};
					//设置定位图标旋转角度
					if(angle) {
						locationMarker.rotateTo(-angle);
						if(others) {
							map.rotateTo({
								to: angle,
								time: 1
							});
						}
					}
					//不同楼层
					if(lastGid !== coord.groupID) {
						lastGid = coord.groupID;
						locationMarker.setPosition(data);
					}
					locationMarker.moveTo(data);
					map.moveTo({
						x: coord.x,
						y: coord.y,
						groupID: coord.groupID,
						time: 1
					});
				}

				//添加定位点图层
				function addlocationMarker(coord) {
					locationMarker = new fengmap.FMLocationMarker({
						//设置图片的路径
						url: 'image/pointer.png',
						//设置图片显示尺寸
						size: 46,
						//设置图片高度
						height: 1,
					});
					//添加定位点标注
					map.addLocationMarker(locationMarker);
					//设置定位图标位置
					setLocationMakerPosition(coord, 180);
					return locationMarker;
				};
				//导航
				map.on('mapClickNode', function(event) {
					if(event.nodeType == fengmap.FMNodeType.MODEL && navi != undefined) {
						var modelLabel = event.label;
						var coord;
						// 如果拾取的模型没有Label对象，则使用模型中心点的坐标
						// 有则使用与模型对应的Label对象的坐标。
						if(!modelLabel) {
							coord = {
								x: event.mapCoord.x,
								y: event.mapCoord.y,
								groupID: event.groupID
							}
						} else {
							coord = {
								x: modelLabel.mapCoord.x,
								y: modelLabel.mapCoord.y,
								groupID: event.groupID
							};
						}
						navi.clearAll();
						//						navi.setStartPoint({
						//							x: mapCoord.x,
						//							y: mapCoord.y,
						//							height: 2,
						//							groupID: 1,
						//							url: 'image/start.png',
						//							size: 32
						//						});
						navi.setEndPoint({
							x: coord.x,
							y: coord.y,
							height: 2,
							groupID: coord.groupID,
							url: 'image/end.png',
							size: 32
						});
//						navi.drawNaviLine();
					}
				})
				//开始导航
				$('#navigation').on('click', function() {
					var zhuanXY = {
						x: resultX,
						y: resultY,
					}
					var coord = CoordTransform(zhuanXY);
					coord.groupID = 1;
					//获取当前位置
					navi.setStartPoint({
						x: coord.x,
						y: coord.y,
						height: 2,
						groupID: coord.groupID,
						url: 'image/start.png',
						size: 32
					});
					navi.drawNaviLine();

					//					naviState = true; //修改导航状态
					//					coordIndex = 0;
				});

				function realNavigation(coord) {
					navi.locate(coord);
				}

				function CoordTransform(Coord) {
					//创建转换器
					var trasformer = new fengmap.MapCoordTransform();
					//来至定位系统的参数 定位的原点坐标 已经定位的范围,(矩形对角线的2个点)
					var locOrigion = {
						'x': 0,
						'y': 0
					}; //定位坐标原点
					var locRange = {
						'x': 32.387,
						'y': 32.202
					}; //定位范围

					//根据定位四个角点的地图坐标点
					var mapParas = [];
					mapParas[0] = {
						'x': 13028246.2666,
						'y': 4737041.5179
					}; //定位原点地图坐标
					mapParas[1] = {
						'x': 13028214.5795,
						'y': 4737041.5179
					}; //X轴终点地图坐标
					mapParas[2] = {
						'x': 13028214.5702,
						'y': 4737009.6396
					}; //定位原点对角点地图坐标
					mapParas[3] = {
						'x': 13028246.2666,
						'y': 4737009.6302
					}; //Y轴终点地

					//转换器初始化
					trasformer.init(locOrigion, locRange, mapParas);

					//定位系统中的定位坐标
					var loc = {
						'x': Coord.x,
						'y': Coord.y
					}; //定位系统所返回的坐标点

					//转换后的地图坐标
					var mapCoord = trasformer.transform(loc);
					return mapCoord;
				}

				function WebSocketTest() {
					if("WebSocket" in window) {
						var ws = new WebSocket("wss://www.dowino2o.net:8087/api/websocket?openId=map" + 123456);
						ws.onopen = function() {
							setInterval(function() {
								ws.send("保持心跳");
							}, 50000)
						};
						ws.onmessage = function(evt) {
							var received_msg = evt.data;
							console.log('收到消息：', received_msg);
							try {
								var jsonObj = JSON.parse(received_msg);
								console.log('jsonObj', jsonObj)
								if(jsonObj.x) {
									XYobj = jsonObj;
									console.log('XYobj', XYobj)
								} else {
									return false;
								}

								//做卡尔曼
								var finalXY = suanXY(resultX, resultY, 0, Ldirection, XYobj.x, XYobj.y, _qValue, _rValue)
								resultX = finalXY._data[0][0];
								resultY = finalXY._data[1][0];
								console.log('resultX', resultX)
								console.log('resultY', resultY)

								var zhuanXY = {
									x: resultX,
									y: resultY,
								}
								var coord = CoordTransform(zhuanXY);
								coord.groupID = 1;
								console.log('coord', coord)
								if(naviState) {
									realNavigation(coord);
								} else {
									setLocationMakerPosition(coord, Ldirection)
								}
							} catch(err) {}
						};
						ws.onclose = function() {
							console.log('连接已关闭')
						};
					} else {
						alert("您的浏览器不支持 WebSocket!");
					}
				}

				//计步定位
				function FengZhuangXY() {
					//状态：静止
					var STAY = 0;
					//状态：运动
					var MOVE = 1;
					//运动状态判断数组，长度20
					var stateValue = new Array(20).fill(0);
					//加速度数组  长度100
					var Accs = new Array(100).fill(0);;
					//每次传入加速度的时间，省去定时器 长度100
					var time = new Array(100).fill(0);
					//数组下标
					var count = 0;
					//行走步数
					var Step = 0;
					//步长
					var Length = 0;
					//行进距离
					var Distance = 0;
					var RDistance = 0;
					//状态
					var State = STAY;

					var currentTime, lastTime, timeCount;

					//监听方向变化
					try {
						window.addEventListener("deviceorientation", orientationHandler, false);

						function orientationHandler(event) {
							Ldirection = Math.round(event.webkitCompassHeading);
							Ldirection += 135;
							Ldirection += 180;
							if(Ldirection > 360) {
								Ldirection -= 360;
							}
							setLocationMakerPosition(null, Ldirection);
						}
					} catch(e) {};
					//监听加速计变化
					if(window.DeviceMotionEvent) {
						window.addEventListener('devicemotion', deviceMotionHandler, false);
					}
					var vibrateSupport = "vibrate" in navigator
					if(vibrateSupport) { //兼容不同的浏览器
						navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate;
					}

					function deviceMotionHandler(eventData) {
						var acceleration = eventData.accelerationIncludingGravity;
						var valuesArray = [acceleration.x, acceleration.y, acceleration.z];
						if(!lastTime) {
							lastTime = new Date().getTime();
						}
						currentTime = new Date().getTime();
						let timeCha = currentTime - lastTime;

						if(timeCha > 1500) {
							_qValue = 0.001;
							_rValue = 0.01;
						} else {
							_qValue = 0;
							_rValue = 1;
						}
						refreshAcc(valuesArray, currentTime);
					}

					function refreshAcc(values, timestamp) {
						Accs[count] = Math.sqrt(values[0] * values[0] + values[1] * values[1] + values[2] * values[2]);
						time[count] = timestamp;
						//检查运动状态
						stateValue[count % 20] = Accs[count];
						checkState();
						//设置检测点，检测点的值为到最新数据的距离，如果太近了将无法确定其为波峰波谷
						//检测点的作用是来减少计算量
						var ckpoint = Accs.length / 5;
						//运动状态判断加上判断检测点是否有波谷存在
						if(State == MOVE && Accs[(count - ckpoint + Accs.length) % Accs.length] < Accs[(count - ckpoint + Accs.length + 1) % Accs.length] &&
							Accs[(count - ckpoint + Accs.length) % Accs.length] <
							Accs[(count - ckpoint + Accs.length - 1) % Accs.length]) {
							//求均值
							var ave0 = 0;
							for(var i = 0; i < Accs.length; ++i) {
								ave0 += Accs[i];
							}
							ave0 /= Accs.length;
							//调整数组顺序，把新数据放在前面，同时把数据减去均值
							var data = new Array(Accs.length).fill(0);
							for(var i1 = 0, j = count; i1 < data.length; ++i1, --j) {
								if(j < 0) {
									j += data.length
								};
								data[i1] = Accs[j] - ave0;
							}
							//寻找波峰波谷
							var sign = new Array(Accs.length).fill(0);
							for(var i2 = 1; i2 < Accs.length - 1; ++i2) {
								if(Math.abs(data[i2]) > 0.8 &&
									Math.abs(2 * data[i2]) > Math.abs((data[i2 - 1] + data[i2 + 1]))) {
									if(data[i2] > 0) {
										sign[i2] = 1;
									} else {
										sign[i2] = -1;
									}
								}
							}

							for(var i3 = 1; i3 < sign.length - 1;) {
								var idx = i3;
								while(++i3 < sign.length - 1 &&
									(sign[i3] == 0 || sign[i3] == sign[idx])) {
									if(sign[i3] != 0 && Math.abs(data[i3]) > Math.abs(data[idx])) {
										sign[idx] = 0;
										idx = i3;
									} else {
										sign[i3] = 0;
									}
								}
							}
							//再次判断检测点是否是波谷
							if(sign[ckpoint] < 0) {
								var index = ckpoint;
								//寻找下个波峰
								while(++index < sign.length && sign[index] == 0);
								if(index < sign.length && sign[index] > 0) {
									var peak = index;
									//寻找下个波谷
									while(++index < sign.length && sign[index] == 0);
									if(index < sign.length && sign[index] < 0) {
										var valley = index;
										//计算H和T
										var H = data[peak] - 0.5 * data[ckpoint] - 0.5 * data[valley];
										var T = time[(count - ckpoint + time.length) % time.length] - time[(count - valley + time.length) % time.length];
										if(H > 1 && T > 300 && T < 1400) {
											_qValue = 0;
											_rValue = 1;
											lastTime = new Date().getTime();
											//步长计算
											var steplength = 0.35 - 0.000155 * T + 0.1638 * Math.sqrt(H);
											//var steplength = 0.65 - 0.000155 * T + 0.1638 * Math.sqrt(H);
											Length = (Length + steplength) / 2;
											Distance += steplength;
											++Step;
											//做卡尔曼
											var finalXY = suanXY(resultX, resultY, steplength, Ldirection, XYobj.x, XYobj.y, _qValue, _rValue)
											resultX = finalXY._data[0][0];
											resultY = finalXY._data[1][0];
											var zhuanXY = {
												x: resultX,
												y: resultY,
											}
											var coord = CoordTransform(zhuanXY);
											coord.groupID = 1;
											console.log('coord', coord)
											if(naviState) {
												realNavigation(coord);
											} else {
												setLocationMakerPosition(coord, Ldirection)
											}
										}
									}
								}
							}
						}
						if(++count == 100) count = 0;
					}

					//检查运动状态
					function checkState() {
						var ave = 0;
						var Var = 0;
						//求均值
						for(var i = 0; i < stateValue.length; i++) {
							ave += stateValue[i];
						}
						ave /= stateValue.length;
						//求方差
						for(var i = 0; i < stateValue.length; i++) {
							Var += (stateValue[i] - ave) * (stateValue[i] - ave);
						}
						Var /= stateValue.length;
						//状态判决
						State = Var > 0.1 ? MOVE : STAY;
					}
					//获取当前时间戳
					function getCurrentTime() {
						var timestamp = new Date().getTime();
						return timestamp;
					}
				}
				
				//显示路径数据
				function cardInfo(data) {
					//距终点的距离
					var distance = data.remain;
					//路线提示信息
					var prompt = navi.naviDescriptions[data.index];
					//当距离小于距离终点的最大距离时结束导航
					if(distance < maxEndDistance) {
						distance = 0;
						prompt = '到达终点';
//						navigation = true;
						//楼层控件可点击
//						groupControl.enableExpand = true;
//						$('#navigation').removeClass('btn-primary');
//						map.mapScaleLevel = startNaviScaleLevel; //还原地图为导航前缩放比例
					}

					//普通人每分钟走80米。
					var time = distance / 80;

					var m = parseInt(time);

					var s = Math.floor((time % 1) * 60);

					$('#description').html('<p>距终点：' + distance.toFixed(1) + ' 米</p><p>大约需要：  ' + m + '  分钟   ' + s + '   秒</p><p>路线提示：' + prompt + ' </p>');
//					$('.layerMask').html('F' + data.groupID);
				};
			};
		</script>
	</body>

</html>